#include "Threadpool.hpp"

#include <unistd.h>

#include <iostream>

using std::cout;
using std::endl;


namespace wd
{


Threadpool::Threadpool(int threadNum, int sz)
: _threadNum(threadNum)
, _queSize(sz)
, _taskque(_queSize)
, _isExit(false)
{
    _threads.reserve(_threadNum);
}

void Threadpool::start()
{
    //先创建Thread的对象
    for(int i = 0; i < _threadNum; ++i) {
        //在创建子线程的时候，将线程池要交给子线程做的任务
        //doTask方法注册给子线程
        unique_ptr<Thread> up(
            new Thread(std::bind(&Threadpool::doTask, this)));
        _threads.push_back(std::move(up));
    }

    //开始运行每一个子线程
    for(auto & pthread : _threads) {
        pthread->start();
    }
}

//停止线程池的运行
void Threadpool::stop()
{
    //当任务队列中还有任务时，等待任务执行结束
    while(!_taskque.empty()) {
        sleep(5);
        //usleep(10000);
    }

    //将退出的标志位设置为true
    _isExit = true;

    _taskque.wakeup();

    //回收每一个子线程
    for(auto & pthread : _threads) {
        pthread->join();
    }
}

//线程池对外提供的添加任务的接口
//充当的是生产者的角色
void Threadpool::addTask(Task task)
{
    if(task) {
        //往任务队列中添加任务
        _taskque.push(task);
    }
}

//线程池对象交给每一个子线程要做的事儿
//充当的是消费者角色
void Threadpool::doTask()
{
    while(!_isExit) {
        //不断的从任务队列中获取任务,本质上是一个函数对象
        Task task = _taskque.pop();
        if(task) {
            //当任务执行的速度比较慢时，在回到while开头时
            //发现_isExit设置为true了，那就可以正常退出子线程
            //
            //如果任务执行的速度比较快， 在stop函数将
            //_isExit设置为true之前,就回到了while循环开始的位置
            //此时继续进入while循环，再阻塞在_taskque.pop方法之上了
            //
            task();
        }
    }

}

}//end of namespace wd
